﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics.Contracts;

namespace Postnuclear.Collections.Adapters
  {
  /// <summary>
  /// Adapts <see cref="INotifyCollectionChanged{T}"/> to <see cref="INotifyCollectionChanged"/>.
  /// </summary>
  /// <typeparam name="T">Type of items in source <see cref="INotifyCollectionChanged{T}"/>.</typeparam>
  public sealed class NotifyCollectionChangedAdapter<T>
    : INotifyCollectionChanged
    {
    #region Public

    // Constructors

    /// <summary>
    /// Initializes a new instance of the <see cref="NotifyCollectionChangedAdapter{T}"/> class.
    /// </summary>
    /// <param name="source">The source.</param>
    public NotifyCollectionChangedAdapter(INotifyCollectionChanged<T> source)
      {
      Contract.Requires<ArgumentNullException>(source != null);

      source.CollectionCleared += OnCollectionCleared;
      source.ItemAdded += OnItemAdded;
      source.ItemRemoved += OnItemRemoved;
      }

    // Events

    /// <summary>
    /// Occurs when the collection changes.
    /// </summary>
    public event NotifyCollectionChangedEventHandler CollectionChanged;

    #endregion

    #region Private

    private void OnCollectionCleared(object sender, ValueEventArgs<IEnumerable<T>> e)
      {
      if (CollectionChanged != null)
        {
        CollectionChanged(sender, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }
      }

    private void OnItemAdded(object sender, ObservableItemEventArgs<T> e)
      {
      if (CollectionChanged != null)
        {
        CollectionChanged(sender, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, e.Item, e.Index));
        }
      }

    private void OnItemRemoved(object sender, ObservableItemEventArgs<T> e)
      {
      if (CollectionChanged != null)
        {
        CollectionChanged(sender, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, e.Item, e.Index));
        }
      }

    #endregion
    }
  }